import { StructuredNode, SendRequest } from './types';

export interface ModelProvider {
  /** Start generating nodes for the given request. */
  generate(req: SendRequest & { requestId: string }): AsyncIterable<StructuredNode>;
  /** Cancel in-flight generation for a requestId, if supported. */
  cancel?(requestId: string): Promise<void> | void;
}

/**
 * A simple in-memory provider that simulates a model stream for testing.
 */
export class InMemoryProvider implements ModelProvider {
  constructor(private readonly script?: (req: SendRequest & { requestId: string }) => AsyncIterable<StructuredNode>) {}

  async *generate(req: SendRequest & { requestId: string }): AsyncIterable<StructuredNode> {
    if (this.script) {
      yield* this.script(req);
      return;
    }
    // Default scripted demo: thinking → raw response → tool use → memory → suggested → main finished
    const now = Date.now();
    yield { type: 'THINKING' as any, ts: now, requestId: req.requestId };
    yield { type: 'RAW_RESPONSE' as any, ts: now + 10, requestId: req.requestId, text: 'Thanks for your message. ' };
    yield { type: 'RAW_RESPONSE' as any, ts: now + 20, requestId: req.requestId, text: 'Let me help you with that. ' };

    // Simulate tool usage
    yield {
      type: 'TOOL_USE' as any,
      ts: now + 30,
      requestId: req.requestId,
      tool: 'view',
      input: { path: 'example.ts' }
    };

    // Simulate memory creation
    yield {
      type: 'AGENT_MEMORY' as any,
      ts: now + 40,
      requestId: req.requestId,
      memoryId: `mem_${req.requestId}`,
      content: `User asked: "${req.requestMessage}"`
    };

    yield { type: 'RAW_RESPONSE' as any, ts: now + 50, requestId: req.requestId, text: 'Here is the complete response.' };
    yield { type: 'SUGGESTED_QUESTIONS' as any, ts: now + 60, requestId: req.requestId, questions: ['Why?', 'How?', 'Next steps?'] };
    yield { type: 'MAIN_TEXT_FINISHED' as any, ts: now + 70, requestId: req.requestId };
  }

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  async cancel(_requestId: string): Promise<void> { /* no-op for in-memory */ }
}

